#ifndef __MQ_CONNECTION_HPP__
#define __MQ_CONNECTION_HPP__

#include "mq_channel.hpp"

namespace mq
{
    class Connection
    {
    public:
        using ptr=std::shared_ptr<Connection>;
        Connection(const VirtualHost::ptr& host,
                    const ConsumerManager::ptr& cmp,
                    const ProtobufCodecPtr& codec,
                    const muduo::net::TcpConnectionPtr& conn,
                    const ThreadPool::ptr& pool):_conn(conn),
                    _codec(codec),_cmp(cmp),_host(host),
                    _pool(pool),_channels(std::make_shared<ChannelManager>()){}

        /*打开信道*/           
        void openChannel(const openChannelRequestPtr& req)
        {
            bool ret=_channels->openChannel(req->cid(),_host,_cmp,_codec,_conn,_pool);
            if(ret==false)
            {
                DLOG("创建信道的时候,信道ID重复了");
                return basicResponse(false,req->rid(),req->cid());
            }
            return basicResponse(true,req->rid(),req->cid());
        }

        /*关闭信道*/
        void closeChannel(const closeChannelRequestPtr& req)
        {
            _channels->closeChannel(req->cid());
            return basicResponse(true,req->rid(),req->cid());
        }

        /*根据信道ID获取信道句柄*/
        Channel::ptr getChannel(const std::string& cid)
        {
            return _channels->getChannel(cid);
        }
    private:
        /*通用回复响应接口*/
        void basicResponse(bool ok,const std::string& rid,const std::string& cid)
        {
            basicCommonResponse resp;
            resp.set_cid(cid);
            resp.set_ok(ok);
            resp.set_rid(rid);
            _codec->send(_conn,resp);
        }
    private:
        muduo::net::TcpConnectionPtr _conn;//通信句柄
        ProtobufCodecPtr _codec;//protobuf协议句柄
        ConsumerManager::ptr _cmp;//消费者管理句柄
        VirtualHost::ptr _host;//虚拟机句柄
        ThreadPool::ptr _pool;//线程池句柄
        ChannelManager::ptr _channels;//信道管理句柄
    };

    class ConnectionManager
    {
    public:
        using ptr=std::shared_ptr<ConnectionManager>;
        ConnectionManager(){}

        /*新建链接*/
        void newConnection(const VirtualHost::ptr& host,
                            const ConsumerManager::ptr& cmp,
                            const ProtobufCodecPtr& codec,
                            const muduo::net::TcpConnectionPtr& conn,
                            const ThreadPool::ptr& pool)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto iter=_conns.find(conn);
            if(iter!=_conns.end()) return;
            auto self_conn=std::make_shared<Connection>(host,cmp,codec,conn,pool);
            _conns.insert(std::make_pair(conn,self_conn));
            return;
        }

        /*释放链接*/
        void delConnection(const muduo::net::TcpConnectionPtr& conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _conns.erase(conn);
        }

        /*根据muduo库链接句柄获取链接*/
        Connection::ptr getConnection(const muduo::net::TcpConnectionPtr& conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto iter=_conns.find(conn);
            if(iter==_conns.end()) return Connection::ptr();
            return iter->second;
        }
    private:
        std::mutex _mutex;
        std::unordered_map<muduo::net::TcpConnectionPtr,Connection::ptr> _conns;
    };
}

#endif